package com.simplerobot.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.simplerobot.consume.PageConsume;
import com.simplerobot.robot.Spider;
import com.simplerobot.util.ClassUtil;
import com.simplerobot.util.FileUtil;


import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 应用上下文
 * Created by liangcq on 2017/3/29.
 */
public class AppContext {

    public static JSONObject config;
    /*Service Map<"Service类名称","实例">*/
    public static Map<String, Object> services = new HashMap<>();
    /*爬虫 Map<"爬虫名称","爬虫实例">*/
    public static Map<String, Spider> spiders = new HashMap<>();
    /*爬取结果页面消费者*/
    public static PageConsume pageConsume;

    public static void putService(String name, Object service) {
        if (!services.containsKey(name)) {
            services.put(name, service);
        }
    }

    public static Object getService(Class service) {
        return services.get(service.getName());
    }

    public static void initAndRun() {
        config = JSON.parseObject(FileUtil.readAllText(Thread.currentThread().getContextClassLoader().getResource("config.json").getPath()));
        /*Dao初始化*/
        initDao(config.getString("daoPackageName"));
        /*service 实例化*/
        List<Class<?>> servicesClass = ClassUtil.getClasses(config.getString("servicepackage"));
        String serviceName;
        BaseService service;
        Object trueService;
        Class inf;
        for (Class cla : servicesClass) {
            if (!cla.isInterface()) {
                serviceName = cla.getName();
                inf = cla.getInterfaces()[0];
                try {
                    service = (BaseService) cla.newInstance();
                    trueService = createServiceProxy(inf, service);
                    AppContext.putService(serviceName, trueService);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }


        }
        //初始化消费者
        pageConsume = new PageConsume();
        initSpider();
        run();
    }

    private static void initDao(String packageName) {
        SysSqlSessionFactory.init(packageName);
    }

    /**
     * 启动爬虫和启动爬取页面消费者
     */
    private static void run(){
        spiders.forEach((name,spider)->{
            System.out.println("运行爬虫");
            spider.run();
        });
        System.out.println("执行消费");
        pageConsume.eat();

    }

    /**
     * 初始化蜘蛛
     */
    private static void initSpider() {
        JSONArray spidersConfig = config.getJSONArray("spider");
        JSONObject spiderConfig;
        String spiderName;
        String spiderClassName;
        String url;
        List<String> spiderNames = new ArrayList<>();
        for(int i=0,size=spidersConfig.size();i<size;i++){
            spiderConfig = spidersConfig.getJSONObject(i);
            spiderName = spiderConfig.getString("name");
            spiderNames.add(spiderName);
            spiderClassName = spiderConfig.getString("class");
            url = spiderConfig.getString("url");
            Spider spider = null;
            try {
                spider = (Spider)Class.forName(spiderClassName).newInstance();
                spider.setSpiderName(spiderName);
                spider.setUrl(url);
                spider.setPageConsume(pageConsume);
            } catch (Exception e) {
                e.printStackTrace();
            }
            spiders.put(spiderName,spider);
        }
        pageConsume.setSpiderNames(spiderNames);
    }

    /**
     * 创建Service动态代理
     * @param inf
     * @param service
     * @return
     */
    private static Object createServiceProxy(Class inf, BaseService service) {
        Object serviceProxy =
                Proxy.newProxyInstance(
                        inf.getClassLoader(), //代理接口加载器
                        new Class[]{inf},  //该代理要实现的接口
                        new ServiceProxy(service)); //Handler实现
        return serviceProxy;
    }
}
